package com.tscnd.core.aspect;

import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.UUID;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;

import com.tscnd.core.annotation.LogWrite;
import com.tscnd.core.entity.log.OptionLog;
import com.tscnd.core.service.log.IOptionLogService;
import com.tscnd.core.utils.DateUtils;
import com.tscnd.core.utils.SysContextUtil;
import com.tscnd.core.utils.TCPIPUtil;

@Aspect //该注解标示该类为切面类   
@Component
public class LogAspect {
	
	private static  final transient Logger log = Logger.getLogger(LogAspect.class);
	
	@Autowired
	private IOptionLogService optionLogService;
	
	/**
	 * 在方法执行后运行
	 * @param point //aop 连接点（所关注的目标对象）
	 * @param lw //自定义注解 传参数接口
	 * @throws Throwable
	 */
	@SuppressWarnings("unused")
	@AfterReturning(pointcut="execution(* com.tscnd.core.service..*.*(..)) && @annotation(lw)")
	public void addLog(JoinPoint point, LogWrite lw) throws Throwable{
		Object[] parames = point.getArgs();//获取目标方法体参数   
		String className = point.getTarget().getClass().toString();//获取目标类名   
		className = className.substring(className.indexOf("com"));  
		String signature = point.getSignature().toString();//获取目标方法签名   
		String methodName = signature.substring(signature.lastIndexOf(".")+1, signature.indexOf("("));   
		String modelName = getModelName(className); //根据类名获取所属的模块
		String ip=TCPIPUtil.getIp(SysContextUtil.getRequest());
		String name=SecurityContextHolder.getContext().getAuthentication().getName();
		OptionLog optionLog=new OptionLog();
		optionLog.setId(UUID.randomUUID().toString());
		optionLog.setClassName(className);
		optionLog.setMethodName(methodName);
		optionLog.setModeName(lw.modeName());
		optionLog.setOptionDesc(lw.desc());
		optionLog.setIp(ip);
		optionLog.setOperationTime(new Date());
		optionLog.setErr("ok");
		optionLog.setState(1);
		optionLogService.save(optionLog);
		log.info("操作成功后日志..");
	}
	@SuppressWarnings("unused")
	 @AfterThrowing(pointcut="execution(* com.tscnd.core.service..*.*(..)) && @annotation(lw)", throwing="ex")
	public void addLog(JoinPoint point, LogWrite lw,Exception ex) throws Throwable{
		 Object[] parames = point.getArgs();//获取目标方法体参数   
			String className = point.getTarget().getClass().toString();//获取目标类名   
			className = className.substring(className.indexOf("com"));  
			String signature = point.getSignature().toString();//获取目标方法签名   
			String methodName = signature.substring(signature.lastIndexOf(".")+1, signature.indexOf("("));   
			String modelName = getModelName(className); //根据类名获取所属的模块
			String ip=TCPIPUtil.getIp(SysContextUtil.getRequest());
			
			OptionLog optionLog=new OptionLog();
			optionLog.setId(UUID.randomUUID().toString());
			optionLog.setClassName(className);
			optionLog.setMethodName(methodName);
			optionLog.setModeName(lw.modeName());
			optionLog.setOptionDesc(lw.desc());
			optionLog.setIp(ip);
			optionLog.setOperationTime(new Date());
			optionLog.setErr(ex.getMessage());
			optionLog.setState(0);
			optionLogService.save(optionLog);
			log.info("操作失败后日志..");
	}
	 
	 /**  
	     * 根据包名查询检索其所属的模块  
	     * @param packageName 包名  
	     * @return 模块名称  
	     */  
	@SuppressWarnings("unused")
	private String getModelName(String packageName){   
	        String modelName = "";   
	        SAXReader reader = new SAXReader();   
	        try {   
	            //读取project.xml模块信息描述xml文档   
//	            File proj = ResourceUtils.getFile("classpath:project.xml");   
//	            Document doc = reader.read(proj);   
//	            //获取文档根节点   
//	            Element root = doc.getRootElement();   
//	            //查询模块名称   
//	            modelName = searchModelName(root, packageName);   
	        } catch (Exception e) {   
	            e.printStackTrace();   
	        }   
	        return modelName;   
	    }   
	  /**
     * 根据xml文档逐个节点检索模块名称
     * @param element 节点元素
     * @param packageName 包名
     * @return 模块名称
     */
    private String searchModelNodes(Element element, String packageName){
            
            String modelName = "";
            Element modules = element.element("modules");
            @SuppressWarnings("rawtypes")
            Iterator it = modules.elementIterator();
            if(!it.hasNext()){
                    return modelName;
            }
            while (it.hasNext()) {
                    Element model = (Element) it.next();
                    String pack = model.attributeValue("packageName");
                    String name = model.elementText("moduleCHPath");
                    if(packageName.equals(pack)){
                            modelName = name;
                            return modelName;
                    }
                    if(modelName!=null && !modelName.equals("")){
                            break;
                    }
                    modelName = searchModelNodes(model, packageName);
            }
            
            return modelName;
    }
    
    /**  
     * 采用递归方式根据包名逐级检索所属模块  
     * @param element 元素节点  
     * @param packageName 包名  
     * @return 模块名称  
     */  
    @SuppressWarnings("unused")
    private String searchModelName(Element element, String packageName){   
        String modelName = searchModelNodes(element, packageName);   
        //若将包名解析到最后的根目录后仍未检索到模块名称，则返回空   
        if(packageName.lastIndexOf(".")==-1){   
            return modelName;   
        }   
        //逐级检索模块名称   
        if(modelName.equals("")){   
            packageName = packageName.substring(0, packageName.lastIndexOf("."));   
            modelName = searchModelName(element, packageName);   
        }   
        return modelName;   
    }   
    
    /**
     * 解析方法参数
     * @param parames 方法参数
     * @return 解析后的方法参数
     */
    @SuppressWarnings("unused")
	private String parseParames(Object[] parames) {
            StringBuffer sb = new StringBuffer();
            for(int i=0; i<parames.length; i++){
                    if(parames[i] instanceof Object[] || parames[i] instanceof Collection){
                            JSONArray json = JSONArray.fromObject(parames[i]);
                            if(i==parames.length-1){
                                    sb.append(json.toString());
                            }else{
                                    sb.append(json.toString() + ",");
                            }
                    }else{
                            JSONObject json = JSONObject.fromObject(parames[i]);
                            if(i==parames.length-1){
                                    sb.append(json.toString());
                            }else{
                                    sb.append(json.toString() + ",");
                            }
                    }
            }
            String params = sb.toString();
            params = params.replaceAll("(\"\\w+\":\"\",)", "");
            params = params.replaceAll("(,\"\\w+\":\"\")", "");
            return params;
    }

    public static void main(String[] args){
    	SimpleDateFormat simpformat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    	String strTime=simpformat.format(new Date());
    	System.out.println(strTime);
    	
    	 Date s=DateUtils.convertStringToStrigulaDate(strTime);
    	 System.out.println(s);

    }
    
}
